package com.zhuanzhuan.hero.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bj58.youpin.common.utils.json.JsonUtils;
import com.bj58.zhuanzhuan.merchant.entity.MerchantAll;
import com.bj58.zhuanzhuan.zzuser.entity.ZZUser;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhuanzhuan.hero.biz.common.util.WxWarnTemplateUtil;
import com.zhuanzhuan.hero.user.consts.Consts;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.dto.auth.CommitAuthDTO;
import com.zhuanzhuan.hero.user.entity.HeroUserAudit;
import com.zhuanzhuan.hero.user.entity.HeroUserAuthentication;
import com.zhuanzhuan.hero.user.entity.HeroUserInfo;
import com.zhuanzhuan.hero.user.enums.*;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.helper.BmWarehouseHelper;
import com.zhuanzhuan.hero.user.helper.SpamlogicHeleper;
import com.zhuanzhuan.hero.user.helper.ZzMerchantHelper;
import com.zhuanzhuan.hero.user.helper.ZzUserHelper;
import com.zhuanzhuan.hero.user.mapper.HeroUserAuthenticationMapper;
import com.zhuanzhuan.hero.user.mq.dto.BaseUserMsg;
import com.zhuanzhuan.hero.user.mq.producer.HeroUserProducer;
import com.zhuanzhuan.hero.user.pojo.bo.BmWarehouseBO;
import com.zhuanzhuan.hero.user.pojo.bo.EnterpriseAuthResultBO;
import com.zhuanzhuan.hero.user.pojo.bo.RealnameAuthResultBO;
import com.zhuanzhuan.hero.user.pojo.bo.TipsBO;
import com.zhuanzhuan.hero.user.service.HeroUserAuditService;
import com.zhuanzhuan.hero.user.service.HeroUserAuthenticationService;
import com.zhuanzhuan.hero.user.service.HeroUserInfoService;
import com.zhuanzhuan.hero.user.service.IApolloService;
import com.zhuanzhuan.hero.user.util.Assert;
import com.zhuanzhuan.hero.user.vo.auth.UserAuthDetailVO;
import com.zhuanzhuan.hero.user.vo.auth.UserAuthResultVO;
import com.zhuanzhuan.hero.user.vo.auth.UserAuthStateVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * dal Interface:HeroUserAuthentication
 * @author hanjunjun
 * @date 2024-6-17
 */
@Service
@Slf4j
public class HeroUserAuthenticationServiceImpl extends ServiceImpl<HeroUserAuthenticationMapper, HeroUserAuthentication>
    implements HeroUserAuthenticationService {

    @Autowired
    private HeroUserAuthenticationMapper heroUserAuthenticationMapper;

    @Resource
    private SpamlogicHeleper spamlogicHeleper;

    @Resource
    private HeroUserAuditService userAuditService;

    @Resource
    private HeroUserInfoService userInfoService;

    @Resource
    private ZzUserHelper zzUserHelper;

    @Resource
    private BmWarehouseHelper bmWarehouseHelper;

    @Resource
    private ZzMerchantHelper zzMerchantHelper;

    @Resource
    private HeroUserProducer heroUserProducer;

    @Resource
    private IApolloService apolloService;

    @Override
    public Long insertSelective(HeroUserAuthentication record){
        return heroUserAuthenticationMapper.insertSelective(record);
    }

    @Override
    public boolean updateByUid(Long uid, HeroUserAuthentication update) {
        LambdaUpdateWrapper<HeroUserAuthentication> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(HeroUserAuthentication::getUid, uid)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());
        this.update(update, updateWrapper);

        //发mq
        heroUserProducer.sendAuthenticationInfoUpdate(new BaseUserMsg(uid));

        return true;
    }

    @Override
    public Long registInitUserAuthenticationInfo(Long uid) {
        HeroUserAuthentication userAuthentication = new HeroUserAuthentication();
        userAuthentication
            .setUid(uid)
            .setIsRealNameAuth(NumConsts.ZERO)
            .setIsEnterpriseAuth(NumConsts.ZERO)
            .setIsBmWarehouseAuth(NumConsts.ZERO)
            .setIsZhuanzhuanMerchantAuth(NumConsts.ZERO)
            .setIsRecyclerAuth(NumConsts.ZERO)
            .setIsEMerchantAuth(NumConsts.ZERO)
            .setIsLargeGoodsAuth(NumConsts.ZERO)
            .setIsDouyinTalent(NumConsts.ZERO)
            .setIsDouyinVAuth(NumConsts.ZERO)
            .setState(StateEnum.EFFECTIVE.getCode())
            .setCreateBy(NumConsts.SYSTEM_CODE)
            .setUpdateBy(NumConsts.SYSTEM_CODE);

        return this.insertSelective(userAuthentication);
    }

    @Override
    public boolean realnameAuthSuccess(Long uid) {
        log.info("realnameAuthSuccess uid={}", uid);
        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        if (Objects.isNull(userAuthentication)) {
            log.info("record不存在");
            return true;
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsRealNameAuth())) {
            log.info("已认证");
            return true;
        }

        //查询认证结果
        RealnameAuthResultBO authResult = spamlogicHeleper.queryRealnameAuthResult(uid);
        if (!NumConsts.ONE.equals(authResult.getSelfAuthStatus())) {
            log.info("认证结果不是认证成功");
            return true;
        }

        //更新
        HeroUserAuthentication update = new HeroUserAuthentication();
        update.setIsRealNameAuth(NumConsts.ONE);
        update.setRealName(authResult.getSelfAuthName());
        update.setIdNumber(authResult.getSelfAuthIdCard());
        update.setUpdateBy(NumConsts.SYSTEM_CODE);
        this.updateByUid(uid, update);

        return true;
    }

    @Override
    public boolean enterpriseAuthSuccess(Long uid) {
        log.info("enterpriseAuthSuccess uid={}", uid);

        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        if (Objects.isNull(userAuthentication)) {
            log.info("record不存在");
            return true;
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsEnterpriseAuth())) {
            log.info("已认证");
            return true;
        }

        //查询认证结果
        EnterpriseAuthResultBO authResult = spamlogicHeleper.queryEnterpriseAuthResult(uid);
        if (Objects.isNull(authResult)) {
            log.info("authResult为空，未认证成功");
            return true;
        }

        //更新
        HeroUserAuthentication update = new HeroUserAuthentication();
        update.setIsEnterpriseAuth(NumConsts.ONE);
        update.setEnterpriseName(authResult.getBusinessName());
        update.setEnterpriseLegalPerson(authResult.getFrName());
        update.setUpdateBy(NumConsts.SYSTEM_CODE);
        this.updateByUid(uid, update);

        return true;
    }

    @Override
    public HeroUserAuthentication getByUid(Long uid) {
        LambdaQueryWrapper<HeroUserAuthentication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HeroUserAuthentication::getUid, uid)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());
        return this.getOne(queryWrapper);
    }

    @Override
    public List<HeroUserAuthentication> listByUid(List<Long> uids) {
        LambdaQueryWrapper<HeroUserAuthentication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(HeroUserAuthentication::getUid, uids)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());
        return this.list(queryWrapper);
    }

    @Override
    public List<UserAuthStateVO> queryUserAuthStates(Long uid) {
        List<UserAuthStateVO> voList = new ArrayList<>();
        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        Assert.notNull(userAuthentication, ExceptionMsgEnum.BUSINESS_ERROR);

        TipsBO tipsBO = apolloService.queryTips();

        //实人认证
        voList.add(this.buildAuthVo(UserAuthTypeEnum.REALNAME.getCode(), userAuthentication.getIsRealNameAuth(),
            tipsBO.getRealnameNoAuth(), ""));
        //企业认证
        voList.add(this.buildAuthVo(UserAuthTypeEnum.ENTERPRISE.getCode(), userAuthentication.getIsEnterpriseAuth(),
            "", ""));

        //查询用户所有的审核提交记录
        List<HeroUserAudit> auditList = userAuditService.listByUid(uid);
        Map<Integer, HeroUserAudit> auditTypeMap =
            auditList.stream().collect(Collectors.toMap(HeroUserAudit::getAuditType, Function.identity()));

        //门店认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.STORE.getCode(), auditTypeMap, "", tipsBO));
        //回收商认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.RECYCER.getCode(), auditTypeMap, "", tipsBO));
        //电商平台认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.E_MERCHANT.getCode(), auditTypeMap, "", tipsBO));
        //大货供应商认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.LARGE_GOODS.getCode(), auditTypeMap, "", tipsBO));
        //抖音达人认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.DOUYIN_TALENT.getCode(), auditTypeMap, "", tipsBO));
        //抖音大V认证
        voList.add(this.buildAuditAuthVo(UserAuthTypeEnum.DOUYIN_V.getCode(), auditTypeMap, tipsBO.getDyvAdvanceAudit(), tipsBO));
        //保卖仓
        voList.add(this.buildAuthVo(UserAuthTypeEnum.BM_WAREHOUSE.getCode(), userAuthentication.getIsBmWarehouseAuth(),
            "", tipsBO.getAuthSuccessDefault()));
        //已验机2.0
        voList.add(this.buildAuthVo(UserAuthTypeEnum.ZHUANZHUAN_MERCHANT.getCode(), userAuthentication.getIsZhuanzhuanMerchantAuth(),
            "", tipsBO.getAuthSuccessDefault()));

        return voList;
    }

    @Override
    public Integer isRealnameAuth(Long uid) {
        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        Assert.notNull(userAuthentication, ExceptionMsgEnum.BUSINESS_ERROR);

        Integer isRealNameAuth = userAuthentication.getIsRealNameAuth();
        return Objects.nonNull(isRealNameAuth) ? isRealNameAuth : NumConsts.ZERO;
    }

    @Override
    public UserAuthDetailVO queryUserAuthDetail(Long uid, Integer authType) {
        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        Assert.notNull(userAuthentication, ExceptionMsgEnum.BUSINESS_ERROR);

        UserAuthDetailVO vo = new UserAuthDetailVO();

        if (UserAuthTypeEnum.REALNAME.getCode().equals(authType)) {
            vo.setRealname(userAuthentication.getRealName());
            vo.setIdCardNo(userAuthentication.getIdNumber());
        } else if (UserAuthTypeEnum.ENTERPRISE.getCode().equals(authType)) {
            vo.setEnterpriseName(userAuthentication.getEnterpriseName());
            vo.setLegalPersonName(userAuthentication.getEnterpriseLegalPerson());
        } else {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }

        return vo;
    }

    @Override
    public UserAuthResultVO commitUserAuth(Long uid, CommitAuthDTO commitAuthDTO) {
        Integer authType = commitAuthDTO.getAuthType();
        HeroUserAuthentication userAuthentication = this.getByUid(uid);
        Assert.notNull(userAuthentication, ExceptionMsgEnum.BUSINESS_ERROR);

        if (UserAuthTypeEnum.BM_WAREHOUSE.getCode().equals(authType)) {
            return this.bmWarehouseAuth(uid, commitAuthDTO.getBindOrgName(), commitAuthDTO.getBindMobile(),
                userAuthentication);
        } else if (UserAuthTypeEnum.ZHUANZHUAN_MERCHANT.getCode().equals(authType)) {
            return this.zhuanzhaunMerchantAuth(uid, commitAuthDTO.getBindOrgName(), commitAuthDTO.getBindMobile(),
                userAuthentication);
        } else if (UserAuthTypeEnum.getManagementAuditAuthTypeList().contains(authType)) {
            return this.commitManagementAudit(uid, commitAuthDTO);
        } else {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }
    }

    @Override
    public void timedModifyBmWarehouseAuthState(int batchSize) {
        //本地所有已保卖仓认证的 分页查询，多批次去调外部接口
        int pageNum = NumConsts.ONE;
        PageInfo<HeroUserAuthentication> pageInfo;
        do {
            pageInfo = PageHelper.startPage(pageNum++, batchSize)
                .doSelectPageInfo(this::selectAuthenticatedBmWarehouse);
            log.info("pageNum={} pageInfo={}", pageNum - 1, JsonUtils.toJsonWithoutNull(pageInfo));
            try {
                this.doModifyBmWarehouseAuthState(pageInfo.getList());
            } catch (Exception e) {
                //捕获异常，循环继续进行，可完成一部分，后续补偿可以直接全量执行，待执行数会减少
                log.error("doModifyBmWarehouseAuthState异常", e);
                WxWarnTemplateUtil.warnOutService(Consts.SERVICE_NAME, "doModifyBmWarehouseAuthState执行失败");
            }
        } while (pageInfo.isHasNextPage());
    }

    @Override
    public void timedModifyZhuanzhuanMerchantAuthState(int batchSize) {
        //本地所有已商户认证的 分页查询，多批次去调外部接口
        int pageNum = NumConsts.ONE;
        PageInfo<HeroUserAuthentication> pageInfo;
        do {
            pageInfo = PageHelper.startPage(pageNum++, batchSize)
                .doSelectPageInfo(this::selectAuthenticatedZhuanzhuanMerchant);
            log.info("pageNum={} pageInfo={}", pageNum - 1, JsonUtils.toJsonWithoutNull(pageInfo));
            try {
                this.doModifyZhuanzhuanMerchantAuthState(pageInfo.getList());
            } catch (Exception e) {
                //捕获异常，循环继续进行，可完成一部分，后续补偿可以直接全量执行，待执行数会减少
                log.error("doModifyZhuanzhuanMerchantAuthState异常", e);
                WxWarnTemplateUtil.warnOutService(Consts.SERVICE_NAME, "doModifyZhuanzhuanMerchantAuthState执行失败");
            }
        } while (pageInfo.isHasNextPage());
    }

    @Override
    public boolean delByUid(Long uid) {
        LambdaUpdateWrapper<HeroUserAuthentication> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserAuthentication::getState, StateEnum.IS_DELETED.getCode())
            .eq(HeroUserAuthentication::getUid, uid)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());

        return this.update(updateWrapper);
    }

    /**
     * 提交运营审核
     *
     * @param uid
     * @param commitAuthDTO
     * @return com.zhuanzhuan.hero.user.vo.auth.UserAuthResultVO
     * @author  hanjunjun
     * @date 2024/6/29
     **/
    private UserAuthResultVO commitManagementAudit(Long uid, CommitAuthDTO commitAuthDTO) {
        List<String> auditPics = commitAuthDTO.getAuditPics();
        List<String> privacyPics = commitAuthDTO.getPrivacyPics();
        if (CollectionUtils.isEmpty(auditPics) && CollectionUtils.isEmpty(privacyPics)) {
            throw new BusinessException("审核图片不可为空");
        }
        //电商平台审核   一期不要手机号了
        /*if (UserAuthTypeEnum.E_MERCHANT.getCode().equals(commitAuthDTO.getAuthType()) &&
            StringUtils.isBlank(commitAuthDTO.getBindMobile())) {
            throw new BusinessException("电商平台认证手机号不可为空");
        }*/

        userAuditService.createAudit(uid, commitAuthDTO);
        return UserAuthResultVO.buildSuccess();
    }

    private List<HeroUserAuthentication> selectAuthenticatedBmWarehouse() {
        HeroUserAuthentication query = new HeroUserAuthentication();
        query.setIsBmWarehouseAuth(NumConsts.ONE);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return this.getBaseMapper().select(query);
    }

    private List<HeroUserAuthentication> selectAuthenticatedZhuanzhuanMerchant() {
        HeroUserAuthentication query = new HeroUserAuthentication();
        query.setIsZhuanzhuanMerchantAuth(NumConsts.ONE);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return this.getBaseMapper().select(query);
    }

    /**
     * 保卖仓认证
     *
     * @param uid
     * @param bindOrgName
     * @param bindMobile
     * @return com.zhuanzhuan.hero.user.vo.auth.UserAuthResultVO
     * @author  hanjunjun
     * @date 2024/6/28
     **/
    private UserAuthResultVO bmWarehouseAuth(Long uid, String bindOrgName, String bindMobile,
        HeroUserAuthentication userAuthentication) {
        if (StringUtils.isBlank(bindOrgName) || StringUtils.isBlank(bindMobile)) {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }

        //是否已认证
        if (NumConsts.ONE.equals(userAuthentication.getIsBmWarehouseAuth())) {
            log.info("已完成保卖仓认证");
            return UserAuthResultVO.buildSuccess();
        }

        //验证绑定手机号对应的实人信息和申请认证用户的实人信息是否一致
        HeroUserInfo heroUserInfo = userInfoService.getUserByUid(uid);
        Assert.notNull(heroUserInfo, ExceptionMsgEnum.BUSINESS_ERROR);

        //根据绑定手机号查询转转体系下所有uid
        Set<Long> allUid = this.getSameIdCardUids(bindMobile);
        if (CollectionUtils.isEmpty(allUid)) {
            log.info("保卖仓认证用户还未实人认证 uid={}", uid);
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "请确认保卖仓绑定手机号");
        }
        if (!allUid.contains(uid)) {
            //绑定手机号查询到所有的uid不包含登录的uid   说明身份信息不一致
            log.info("绑定手机号与登录手机号认证信息不一致");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "保卖仓认证信息与用户信息不一致");
        }

        //查询保卖仓信息
        List<BmWarehouseBO> bmWarehouse = bmWarehouseHelper.batchGetUidOwnWarehouseInfo(new ArrayList<>(allUid));
        if (CollectionUtils.isEmpty(bmWarehouse)) {
            log.info("查询绑定保卖仓为空");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "请确认保卖仓绑定手机号");
        }
        Map<Long, BmWarehouseBO> warehouseIdMap =
            bmWarehouse.stream().collect(Collectors.toMap(BmWarehouseBO::getWarehouseId, Function.identity(),
                //保卖仓接口可能返回不同uid都绑定一个保卖仓，这儿做一下合并
                (e1,e2) -> e2));

        //是否已经被绑定
        List<Long> warehouseIds = new ArrayList<>(warehouseIdMap.keySet());
        //已绑定的
        List<Long> boundWrehouseIds =
            this.listByBmWarehouseIds(warehouseIds).stream().map(HeroUserAuthentication::getBmWarehouseId)
                .collect(Collectors.toList());
        //筛选出未绑定的
        List<Long> noboundWarehouseIds = warehouseIds.stream().filter(warehouseId -> !boundWrehouseIds.contains(warehouseId))
            .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(noboundWarehouseIds)) {
            log.info("保卖仓已被绑定");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "认证失败，该保卖仓已被其他用户绑定");
        }
        //绑定
        BmWarehouseBO noboundWarehouse = warehouseIdMap.get(noboundWarehouseIds.get(NumConsts.ZERO));
        this.successBmWarehouseAuth(uid, noboundWarehouse.getWarehouseId(), noboundWarehouse.getWarehouseUid(),
            noboundWarehouse.getWarehouseName());
        return UserAuthResultVO.buildSuccess();
    }

    private Set<Long> getSameIdCardUids(String bindMobile) {
        ZZUser bindMobileUser = zzUserHelper.getUserByMobile(bindMobile);
        if (Objects.isNull(bindMobileUser)) {
            log.info("绑定手机号查询用户信息不存在");
            throw new BusinessException("请确认保卖仓绑定手机号");
        }
        Long bindMobileUid = bindMobileUser.getUid();
        return spamlogicHeleper.getSameIdCardAllUid(bindMobileUid);
    }

    /**
     * 转转已验机2.0商户认证
     *
     * @param uid
     * @param bindOrgName
     * @param bindMobile
     * @param userAuthentication
     * @return com.zhuanzhuan.hero.user.vo.auth.UserAuthResultVO
     * @author  hanjunjun
     * @date 2024/6/28
     **/
    private UserAuthResultVO zhuanzhaunMerchantAuth(Long uid, String bindOrgName, String bindMobile,
        HeroUserAuthentication userAuthentication) {
        if (StringUtils.isBlank(bindOrgName) || StringUtils.isBlank(bindMobile)) {
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }

        //是否已认证
        if (NumConsts.ONE.equals(userAuthentication.getIsZhuanzhuanMerchantAuth())) {
            log.info("已完成转转已验机2.0商户认证");
            return UserAuthResultVO.buildSuccess();
        }

        //根据绑定手机号查询转转体系下所有uid
        Set<Long> allUid = this.getSameIdCardUids(bindMobile);
        if (CollectionUtils.isEmpty(allUid)) {
            log.info("已验机2.0认证用户还未实人认证 uid={}", uid);
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "认证失败，未查询到商户信息");
        }
        if (!allUid.contains(uid)) {
            //绑定手机号查询到所有的uid不包含登录的uid   说明身份信息不一致
            log.info("绑定手机号与登录手机号认证信息不一致");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "认证信息与用户信息不一致");
        }

        //多个uid下是否是正在合作中的已验机2.0商户
        List<MerchantAll> merchantList = zzMerchantHelper.getEffectiveByUidsAndBid(new ArrayList<>(allUid));
        if (CollectionUtils.isEmpty(merchantList)) {
            log.info("查询2.0商户为空");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "认证失败，未查询到商户信息");
        }
        Map<Long, MerchantAll> merchantIdMap =
            merchantList.stream().collect(Collectors.toMap(MerchantAll::getUid, Function.identity()));
        List<Long> merchantIds = new ArrayList<>(merchantIdMap.keySet());

        //未被绑定
        List<Long> boundMerchantIds =
            this.listByMerchantIds(merchantIds).stream().map(HeroUserAuthentication::getZhuanzhuanMerchantId)
                .collect(Collectors.toList());
        //筛选出未绑定的
        List<Long> noboundMerchantIds = merchantIds.stream().filter(merchantId -> !boundMerchantIds.contains(merchantId))
            .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(noboundMerchantIds)) {
            log.info("商户已被绑定");
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "认证失败，该商户已被其他用户绑定");
        }

        //绑定
        MerchantAll noboundMerchant = merchantIdMap.get(noboundMerchantIds.get(NumConsts.ZERO));
        this.successZhuanzhuanMerchantAuth(uid, noboundMerchant.getUid());
        return UserAuthResultVO.buildSuccess();
    }

    /**
     * 保卖仓认证成功更新字段
     *
     * @param uid
     * @param warehouseId 站点id
     * @param warehouseUid 站长uid
     * @param warehouseName 站点名称
     * @return void
     * @author  hanjunjun
     * @date 2024/7/27
     **/
    private void successBmWarehouseAuth(Long uid, Long warehouseId, Long warehouseUid, String warehouseName) {
        HeroUserAuthentication update = new HeroUserAuthentication();
        update.setIsBmWarehouseAuth(NumConsts.ONE);
        update.setBmWarehouseId(warehouseId);
        update.setBmWarehouseUid(warehouseUid);
        update.setBmWarehouseName(warehouseName);
        update.setUpdateBy(NumConsts.SYSTEM_CODE);

        this.updateByUid(uid, update);
    }

    private void successZhuanzhuanMerchantAuth(Long uid, Long merchantId) {
        HeroUserAuthentication update = new HeroUserAuthentication();
        update.setIsZhuanzhuanMerchantAuth(NumConsts.ONE);
        update.setZhuanzhuanMerchantId(merchantId);
        update.setUpdateBy(NumConsts.SYSTEM_CODE);
        this.updateByUid(uid, update);
    }

    /**
     * 批量取消保卖仓认证
     *
     * @param ids
     * @return void
     * @author  hanjunjun
     * @date 2024/6/28
     **/
    private void batchCanelBmWarehouseAuth(List<Long> ids) {
        log.info("批量取消保卖仓认证 ids={}", JsonUtils.toJsonWithoutNull(ids));
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        LambdaUpdateWrapper<HeroUserAuthentication> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserAuthentication::getIsBmWarehouseAuth, NumConsts.ZERO)
            .set(HeroUserAuthentication::getBmWarehouseId, null)
            .set(HeroUserAuthentication::getBmWarehouseUid, null)
            .set(HeroUserAuthentication::getBmWarehouseName, null)
            .in(HeroUserAuthentication::getId, ids);
        this.update(updateWrapper);
    }

    /**
     * 批量取消转转已验机2.0商户认证
     *
     * @param ids
     * @return void
     * @author  hanjunjun
     * @date 2024/6/28
     **/
    private void batchCanelZhuanzhuanMerchantAuth(List<Long> ids) {
        log.info("批量取消转转已验机2.0商户认证 ids={}", JsonUtils.toJsonWithoutNull(ids));
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        LambdaUpdateWrapper<HeroUserAuthentication> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserAuthentication::getIsZhuanzhuanMerchantAuth, NumConsts.ZERO)
            .set(HeroUserAuthentication::getZhuanzhuanMerchantId, null)
            .in(HeroUserAuthentication::getId, ids);
        this.update(updateWrapper);
    }

    private List<HeroUserAuthentication> listByBmWarehouseIds(List<Long> warehouseIds) {
        LambdaQueryWrapper<HeroUserAuthentication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(HeroUserAuthentication::getBmWarehouseId, warehouseIds)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());
        return this.list(queryWrapper);
    }

    private List<HeroUserAuthentication> listByMerchantIds(List<Long> merchantIds) {
        LambdaQueryWrapper<HeroUserAuthentication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(HeroUserAuthentication::getZhuanzhuanMerchantId, merchantIds)
            .eq(HeroUserAuthentication::getState, StateEnum.EFFECTIVE.getCode());
        return this.list(queryWrapper);
    }

    private UserAuthStateVO buildAuthVo(Integer authType, Integer isAuth, String failTips, String successTips) {
        UserAuthStateVO authVo = new UserAuthStateVO(authType);
        if (NumConsts.ONE.equals(isAuth)) {
            authVo.setAuthState(UserAuthStateEnum.AUTHENTICATED.getCode());
            authVo.setTips(successTips);
        } else {
            authVo.setAuthState(UserAuthStateEnum.NO_AUTH.getCode());
            authVo.setTips(failTips);
        }
        return authVo;
    }


    private UserAuthStateVO buildAuditAuthVo(Integer authType, Map<Integer, HeroUserAudit> auditTypeMap, String extraTips,
        TipsBO tipsBO) {
        UserAuthStateVO authVO = new UserAuthStateVO(authType);
        HeroUserAudit auditRecord = auditTypeMap.get(authType);
        if (Objects.isNull(auditRecord)) {
            //未认证
            authVO.setAuthState(UserAuthStateEnum.NO_AUTH.getCode());
        } else {
            Integer auditState = auditRecord.getAuditStatus();
            if (AuditStateEnum.WAIT_AUDIT.getCode().equals(auditState)) {
                //审核中
                authVO.setAuthState(UserAuthStateEnum.AUDITING.getCode());
                authVO.setTips(tipsBO.getAuditing());
            } else if (AuditStateEnum.REJECT.getCode().equals(auditState)) {
                //审核驳回
                authVO.setAuthState(UserAuthStateEnum.AUDIT_FAIL.getCode());
                authVO.setTips(String.format(tipsBO.getAuditReject(), auditRecord.getRejectReason()));
            } else if (AuditStateEnum.PASS.getCode().equals(auditState)) {
                //审核通过
                authVO.setAuthState(UserAuthStateEnum.AUTHENTICATED.getCode());
                if (StringUtils.isNotBlank(extraTips)) {
                    authVO.setTips(extraTips);
                } else {
                    authVO.setTips("已通过审核");
                }
            }
        }

        return authVO;
    }

    private void doModifyBmWarehouseAuthState(List<HeroUserAuthentication> authenticatedBmWarehouseRecord) {
        if (CollectionUtils.isEmpty(authenticatedBmWarehouseRecord)) {
            log.info("还没有人进行保卖仓认证");
            return;
        }
        //根据站长uids查询保卖仓
        List<Long> uids = authenticatedBmWarehouseRecord.stream()
            .map(HeroUserAuthentication::getBmWarehouseUid)
            .collect(Collectors.toList());
        List<BmWarehouseBO> bmWarehouses = bmWarehouseHelper.batchGetUidOwnWarehouseInfo(uids);
        //还开启的保卖仓站点id
        List<Long> openWarehouseId = bmWarehouses.stream().map(BmWarehouseBO::getWarehouseId).collect(Collectors.toList());

        //筛选出已关站的 更新
        List<Long> closeWarehouseRecordIds = authenticatedBmWarehouseRecord.stream()
            .filter(record -> !openWarehouseId.contains(record.getBmWarehouseId()))
            .map(HeroUserAuthentication::getId)
            .collect(Collectors.toList());
        this.batchCanelBmWarehouseAuth(closeWarehouseRecordIds);
    }

    private void doModifyZhuanzhuanMerchantAuthState(List<HeroUserAuthentication> authenticatedZhuanzhuanMerchantRecord) {
        if (CollectionUtils.isEmpty(authenticatedZhuanzhuanMerchantRecord)) {
            log.info("还没有人进行商户认证");
            return;
        }
        //根据商户uids查询商户  zhuanzhuanMerchantId就是绑定的用户uid
        List<Long> dbMerchantUids = authenticatedZhuanzhuanMerchantRecord.stream()
            .map(HeroUserAuthentication::getZhuanzhuanMerchantId).collect(Collectors.toList());
        List<MerchantAll> merchants = zzMerchantHelper.getEffectiveByUidsAndBid(dbMerchantUids);
        //还开启的商户id
        List<Long> remoteMerchantIds = merchants.stream().map(MerchantAll::getUid).collect(Collectors.toList());

        //筛选出已不合作的 更新
        List<Long> finalMerchantRecordIds = authenticatedZhuanzhuanMerchantRecord.stream()
            .filter(record -> !remoteMerchantIds.contains(record.getZhuanzhuanMerchantId()))
            .map(HeroUserAuthentication::getId)
            .collect(Collectors.toList());
        this.batchCanelZhuanzhuanMerchantAuth(finalMerchantRecordIds);
    }
}